package com.naiterui.ehp.bs.patient.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.naiterui.common.redis.RedisUtil;
import com.naiterui.ehp.bp.bo.im.MsgSendParamBO;
import com.naiterui.ehp.bp.bo.patient.ConvertWxImageBO;
import com.naiterui.ehp.bp.bo.patient.PatientInquirerBO;
import com.naiterui.ehp.bp.bo.smh.SmhUserBO;
import com.naiterui.ehp.bp.constants.ImConstants;
import com.naiterui.ehp.bp.constants.InquirerRelationEnum;
import com.naiterui.ehp.bp.domain.City;
import com.naiterui.ehp.bp.domain.ConsultSession;
import com.naiterui.ehp.bp.domain.Patient;
import com.naiterui.ehp.bp.domain.PatientInquirerInfo;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.utils.biz.NameUtils;
import com.naiterui.ehp.bp.utils.date.DateUtil;
import com.naiterui.ehp.bp.utils.lang.StringUtil;
import com.naiterui.ehp.bs.patient.constants.CacheConstant;
import com.naiterui.ehp.bs.patient.dao.mongo.ApSessionDao;
import com.naiterui.ehp.bs.patient.exception.ExceptionCodes;
import com.naiterui.ehp.bs.patient.feign.EmrFeginClient;
import com.naiterui.ehp.bs.patient.feign.IDoctorFeignClient;
import com.naiterui.ehp.bs.patient.feign.ImFeginClient;
import com.naiterui.ehp.bs.patient.repository.IApCityRepository;
import com.naiterui.ehp.bs.patient.repository.IApConsultSessionRepository;
import com.naiterui.ehp.bs.patient.repository.IApPatientRepository;
import com.naiterui.ehp.bs.patient.repository.IPatientInquirerRepository;
import com.naiterui.ehp.bs.patient.service.IDrSystemConfService;
import com.naiterui.ehp.bs.patient.service.IPatientDoctorService;
import com.naiterui.ehp.bs.patient.service.IPatientInquirerService;
import com.naiterui.ehp.bs.patient.service.ISendSMSService;
import com.naiterui.ehp.bs.patient.service.function.IFunctionService;
import com.naiterui.ehp.bs.patient.utils.ImgUtil;
import com.naiterui.ehp.bs.patient.vo.doctor.DoctorVO;
import com.naiterui.ehp.bs.patient.vo.inquirer.InquirerInitVO;
import com.naiterui.ehp.bs.patient.vo.inquirer.InquirerParamVO;
import com.naiterui.ehp.bs.patient.vo.inquirer.InquirerRelationVO;
import com.naiterui.ehp.bs.patient.vo.inquirer.InquirerVO;
import com.naiterui.ehp.bs.patient.vo.requestparam.PatientBaseParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description 就这人管理
 * @Author gongbaoqiang
 * @Date 2020/7/9 4:01 PM
 */
@Slf4j
@Service
public class ApPatientInquirerServiceImpl implements IPatientInquirerService {

    @Autowired
    private IPatientInquirerRepository inquirerRepository;

    @Autowired
    private IDrSystemConfService systemConfService;

    @Autowired
    private IPatientDoctorService doctorService;

    @Autowired
    private ISendSMSService sendSMSService;

    @Autowired
    private IFunctionService functionService;

    @Autowired
    private IApCityRepository apCityRepository;
    @Autowired
    private IDoctorFeignClient doctorFeignClient;

    @Autowired
    private IApPatientRepository patientRepository;
    @Autowired
    private ApSessionDao sessionDao;

    @Autowired
    private IApConsultSessionRepository consultSessionRepository;

    @Autowired
    private ImFeginClient imFeginClient;

    @Autowired
    private EmrFeginClient emrFeginClient;

    @Override
    public List<InquirerVO> list(Long patientId, Long doctorId) throws BusinessException {
        List<PatientInquirerInfo> list = inquirerRepository.findByPatientIdAndStatus(patientId, PatientInquirerInfo.STATUS_DEFAULT);
        boolean flag = false;
        //检查当前医生是否是儿科医生
        if (doctorId != null) {
            DoctorVO doctorVO = doctorService.getDoctorByDoctorId(doctorId);
            if (systemConfService.isPediatrics(doctorVO.getDepartmentId())) {
                flag = true;
            }
            }
        Map<String, String> inquirerMap = list.stream().filter(i -> StringUtils.isNotBlank(i.getIdCard()))
                .collect(Collectors.toMap(PatientInquirerInfo::getIdCard, PatientInquirerInfo::getName));
        List<SmhUserBO> patientRecords = new ArrayList<>();
        if (MapUtil.isNotEmpty(inquirerMap)) {
            patientRecords = emrFeginClient.getPatientRecords(inquirerMap);
        }
        Map<String, SmhUserBO> patientRecordMap =
                patientRecords.stream().collect(Collectors.toMap(SmhUserBO::getIdCard, Function.identity(), (a, b) -> b));
        boolean chooseFlag = flag;
        return list.stream().map(s -> {
            InquirerVO vo = new InquirerVO();
            BeanUtils.copyProperties(s, vo);
            vo.setPhone(StringUtils.isNotEmpty(vo.getPhone()) ? vo.getPhone() : "");
            vo.setIdCard(StringUtils.isNotEmpty(vo.getIdCard()) ? vo.getIdCard() : "");
            vo.setInquirerId(s.getId());
            vo.setCanChoose(InquirerVO.CAN_CHOOSE_YES);
            vo.setRelationName(InquirerRelationEnum.getNameByValue(s.getRelation()));
            vo.setMyself(s.getRelation().equals(InquirerRelationEnum.ONESELF.getValue()));
            //设置年龄
            String age = s.getAge();
            vo.setAge(StringUtils.isEmpty(age) ? "未知" : age);

            //儿科医生只能选择18岁以下的就诊人
            if (chooseFlag) {
                if (!s.ageLessThan18()) {
                    vo.setCanChoose(InquirerVO.CAN_CHOOSE_NO);
                }
            }
            // 就诊人是否存在HIS病例
            vo.setHisRecord(false);
            if (patientRecordMap.containsKey(s.getIdCard())) {
                vo.setHisRecord(true);
            }
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public Long saveOrUpdate(InquirerParamVO paramVO) throws BusinessException {
        Long id = paramVO.getInquirerId();
        if (null != id) {
            PatientInquirerInfo patientInquirerInfo = inquirerRepository.get(id);
            // 修改
            if (null == patientInquirerInfo) {
                throw new BusinessException(ExceptionCodes.PARAM_ERROR);
            }
            paramVO.setId(id);
            // 同一个患者下不能出现姓名相同的就诊人
            update(paramVO);
            return id;
        } else {
            // 添加
            return add(paramVO);
        }
    }

    @Override
    public Long findMyselfByPatientId(Long patientId) {
        // 如果没有本人就诊人就找其他就诊人
        return getDefaultInquirerInfoByPatientId(null, patientId).getInquirerId();
//        return inquirerRepository.findFirstByPatientIdAndRelation(patientId, 0).getId();
    }

    public void update(InquirerParamVO paramVO) throws BusinessException {
        if (paramVO.getRelation().equals(InquirerRelationEnum.ONESELF.getValue())) {
            PatientInquirerInfo patientInquirerInfo = inquirerRepository
                .findFirstByPatientIdAndRelation(paramVO.getPatientId(), InquirerRelationEnum.ONESELF.getValue());
            if (null != patientInquirerInfo && !patientInquirerInfo.getId().equals(paramVO.getInquirerId())) {
                throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_ONESELF_HAS_EXIST);
            }
        }

        if (StringUtils.isNotEmpty(paramVO.getName()) && !paramVO.getName().matches(NameUtils.VALIDATE_REGEX_USER_NAME)) {
            throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_NAME_NOT_SPECIFICATION);
        }

        PatientInquirerInfo patientInquirerInfo = inquirerRepository.get(paramVO.getInquirerId());
        // 本人就诊人不让修改关系
        if (patientInquirerInfo.getRelation().equals(InquirerRelationEnum.ONESELF.getValue())
            && !paramVO.getRelation().equals(InquirerRelationEnum.ONESELF.getValue())) {
            throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_ONESELF_NOT_CAN_UPDATE_RELATION);
        }

        BeanUtils.copyProperties(paramVO, patientInquirerInfo);
        if (patientInquirerInfo.getStatus().equals(PatientInquirerInfo.STATUS_DELETE)) {
            // 已删除的记录不能编辑
            throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_DELETE_NOT_UPDATE);
        }

        if (StringUtils.isNotEmpty(paramVO.getIdCard())
            || (paramVO.getChildTag() == 1 && StringUtils.isNotEmpty(paramVO.getGuardianIdCard()))) {
            // 校验身份证号和姓名合法性
            if (paramVO.getChildTag() == 1) {
                doctorFeignClient.verifyIdCard(paramVO.getGuardianIdCard(), paramVO.getGuardianName());
            } else {
                doctorFeignClient.verifyIdCard(paramVO.getIdCard(), paramVO.getName());
            }
        }

        String idCard = paramVO.getIdCard();
        if (StringUtils.isNotEmpty(idCard)) {
            Date birthday = DateUtil.parseStrToCustomPatternDate(IdcardUtil.getBirthByIdCard(idCard), "yyyyMMdd");
            int gender = IdcardUtil.getGenderByIdCard(idCard);
            patientInquirerInfo.setBirthday(birthday);
            patientInquirerInfo.setGender(gender);
        }

        if (StringUtils.isNotEmpty(paramVO.getPhone()) && !StringUtil.isMobileNum(paramVO.getPhone())) {
            throw new BusinessException(ExceptionCodes.SMS_PHONE_ERROR);
        }

        if (paramVO.getChildTag().equals(PatientInquirerInfo.CHILD_TAG_YES) && null != patientInquirerInfo.getBirthday() && !patientInquirerInfo
            .ageLessThan18()) {
            // 添加/编辑 儿童就诊人，大于等于18岁不让操作
            throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_CHILD_AGE_TOO_LONG);
        }

        //关系为本人则更新patient信息
        updatePatientPartInfo(patientInquirerInfo, paramVO.getPatientId());

        /*if (patientInquirerInfo.getRelation().equals(InquirerRelationEnum.ONESELF.getValue())) {
            // 本人就诊人信息同步患者信息
            Patient patient = patientRepository.get(paramVO.getPatientId());
            patient.setName(patientInquirerInfo.getName());
            patient.setPhone(patientInquirerInfo.getPhone());
            patient.setBirthday(patientInquirerInfo.getBirthday());
            patient.setIdCard(patientInquirerInfo.getIdCard());
            patient.setGender(patientInquirerInfo.getGender());
            patientRepository.update(patient);
        }*/
        patientInquirerInfo.setAccountStatus(PatientInquirerInfo.ACCOUNT_STATUS_YES);
        inquirerRepository.update(patientInquirerInfo);
        if (null != paramVO.getIsFirstUpdate() && null != paramVO.getDoctorId() && 1 == paramVO.getIsFirstUpdate()) {
            if(!RedisUtil.keyOps().existsKey(CacheConstant.getInquirerInfoPerfectKey(paramVO.getInquirerId()))){
                sendSysMessage(paramVO.getDoctorId(), paramVO.getPatientId(), paramVO.getInquirerId());
            }
        }
    }

    @Override
    public Long add(InquirerParamVO paramVO) throws BusinessException {
        if (StringUtils.isNotEmpty(paramVO.getName()) && !paramVO.getName().matches(NameUtils.VALIDATE_REGEX_USER_NAME)) {
            throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_NAME_NOT_SPECIFICATION);
        }
        Integer relation = paramVO.getRelation();
        if (null != relation && relation.equals(InquirerRelationEnum.ONESELF.getValue()) && null != inquirerRepository
            .findFirstByPatientIdAndRelationAndStatus(paramVO.getPatientId(), InquirerRelationEnum.ONESELF
                .getValue(), PatientInquirerInfo.STATUS_DEFAULT)) {
            // 就诊人本人不可重复添加
            throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_ONESELF_REPEAT_ADD);
        }
        // 校验身份证号和姓名合法性
        if (StringUtils.isNotEmpty(paramVO.getIdCard())) {
            doctorFeignClient.verifyIdCard(paramVO.getIdCard(), paramVO.getName());
        }
        if (paramVO.getChildTag() == 1 && StringUtils.isNotEmpty(paramVO.getGuardianIdCard())) {
            doctorFeignClient.verifyIdCard(paramVO.getGuardianIdCard(), paramVO.getGuardianName());
        }
        //判断就诊人是否有被删除记录，有则找回
//        PatientInquirerInfo inquirer = inquirerRepository
//            .findByPatientIdAndNameAndIdCard(paramVO.getPatientId(), paramVO.getName(), paramVO.getIdCard());
//        if (inquirer != null) {
//            if (inquirer.getStatus().equals(PatientInquirerInfo.STATUS_DEFAULT)) {
//                throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_ALREADY_EXIST);
//            }
//        } else {
//            inquirer = new PatientInquirerInfo();
//        }
        PatientInquirerInfo inquirer = new PatientInquirerInfo();
        //填写出生日期且年龄大于18岁，则身份证号必填
        /*if (null != paramVO.getBirthday() && StringUtils.isBlank(paramVO.getIdCard())) {
            int age = getAgeByBirth(paramVO.getBirthday());
            if (age >= 18) {
                throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_ID_CARD_EMPTY);
            }
        }*/
        Long inquirerId = inquirer.getId();
        BeanUtils.copyProperties(paramVO, inquirer);
        inquirer.setId(inquirerId);
        inquirer.setAccountStatus(PatientInquirerInfo.ACCOUNT_STATUS_YES);
        //出生证明图片处理:从微信临时目录下载，同步到本地磁盘
        if (StringUtils.isNotBlank(paramVO.getBirthImage())) {
            List<ConvertWxImageBO> imageList = Lists.newArrayList(ConvertWxImageBO.builder().mediaId(paramVO.getBirthImage()).build());
            List<ConvertWxImageBO> result = functionService.convertImage(imageList);
            functionService.syncImageFile(result);
            if (CollectionUtils.isNotEmpty(result)) {
                inquirer.setBirthImage(result.get(0).getImageUrl());
            }
        }
        inquirer.setStatus(PatientInquirerInfo.STATUS_DEFAULT);
        inquirer.setCreatedAt(new Date());

        // 有身份证号直接识别出性别和出生日期
        String idCard = paramVO.getIdCard();
        if (StringUtils.isNotEmpty(idCard)) {
            Date birthday = DateUtil.parseStrToCustomPatternDate(IdcardUtil.getBirthByIdCard(idCard), "yyyyMMdd");
            int gender = IdcardUtil.getGenderByIdCard(idCard);
            log.info("根据身份证信息解析出来的性别 {}, 出生日期 {}", gender, birthday);
            inquirer.setBirthday(birthday);
            inquirer.setGender(gender);
        }

        if (paramVO.getChildTag().equals(PatientInquirerInfo.CHILD_TAG_YES)) {
            if (null == inquirer.getBirthday() || null == inquirer.getGender()) {
                log.info("低龄儿童，性别和出生日期必填, 身份证号 {}，birthday {}, gender {} ", paramVO.getIdCard(), inquirer.getBirthday(), inquirer.getGender());
                // 低龄儿童，如果填写了身份证，则直接识别出性别和出生日期，否则用户必须自己填写性别和出生日期
                throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_BIRTHDAY_EMPTY);
            }

            if (!inquirer.ageLessThan18()) {
                // 添加儿童就诊人，大于等于18岁不让操作
                throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_CHILD_AGE_TOO_LONG);
            }
        }

        if (PatientInquirerInfo.CHILD_TAG_YES != paramVO.getChildTag()) {
            //成人，判断电话号码
            if (StringUtils.isBlank(paramVO.getPhone())) {
                throw new BusinessException(ExceptionCodes.SMS_PHONE_NULL);
            }
            if (!StringUtil.isMobileNum(paramVO.getPhone())) {
                throw new BusinessException(ExceptionCodes.SMS_PHONE_ERROR);
            }
        }

        PatientInquirerInfo result = null;
        if (inquirer.getId() == null) {
            result = inquirerRepository.save(inquirer);
        } else {
            result = inquirerRepository.update(inquirer);
        }
        //关系为本人则更新patient信息
        updatePatientPartInfo(result, paramVO.getPatientId());
        return result.getId();
    }

    /**
     * 根据就诊人与本人关系更新patient部分基本信息
     *
     * @param patientId
     * @throws BusinessException
     */
    private void updatePatientPartInfo(PatientInquirerInfo patientInquirerInfo, Long patientId) throws BusinessException {
        if (InquirerRelationEnum.ONESELF.getValue().equals(patientInquirerInfo.getRelation())) {
            Patient patient = patientRepository.get(patientId);
            if (patient != null) {
                patient.setName(patientInquirerInfo.getName());
                patient.setPhone(patientInquirerInfo.getPhone());
                patient.setBirthday(patientInquirerInfo.getBirthday());
                patient.setIdCard(patientInquirerInfo.getIdCard());
                patient.setGender(patientInquirerInfo.getGender());
                patientRepository.update(patient);
            }
        }
    }

    @Override
    public InquirerVO detail(Long patientId, Long inquirerId) throws BusinessException {
        PatientInquirerInfo inquirerInfo = get(patientId, inquirerId);
        InquirerVO vo = new InquirerVO();
        BeanUtils.copyProperties(inquirerInfo, vo);
        vo.setInquirerId(inquirerId);
        vo.setAge(inquirerInfo.getAge());
        vo.setRelationName(InquirerRelationEnum.getNameByValue(inquirerInfo.getRelation()));
        if (StringUtils.isNotBlank(inquirerInfo.getBirthImage())) {
            vo.setBirthImage(ImgUtil.getWxImgUrl(inquirerInfo.getBirthImage()));
        }
        return vo;
    }

    @Override
    public void del(Long patientId, Long inquirerId) throws BusinessException {
        PatientInquirerInfo inquirerInfo = get(patientId, inquirerId);
        if (inquirerInfo.getRelation().equals(InquirerRelationEnum.ONESELF.getValue())) {
            // 本人就诊人不可以删除
            throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_ONESELF_NOT_DELETE);
        }
        inquirerInfo.setStatus(PatientInquirerInfo.STATUS_DELETE);
        inquirerInfo.setChangedAt(new Date());
        inquirerRepository.update(inquirerInfo);
    }

    @Override
    public InquirerInitVO relationList(Long patientId) throws BusinessException {
        List<PatientInquirerInfo> inquirerInfos = inquirerRepository
            .findByPatientIdAndRelation(patientId, InquirerRelationEnum.ONESELF.getValue());

        List<InquirerRelationVO> relationList = InquirerRelationEnum.getAllList().stream()
            .map(s -> {
                InquirerRelationVO vo = InquirerRelationVO.builder()
                    .relationId(s.getValue())
                    .relationName(s.getName())
                    .gender(s.getGender())
                    .build();
                /*if (s.equals(InquirerRelationEnum.SPOUSE)) {
                    vo.setGender(selfGender == 0 ? 1 : 0);
                }*/
                return vo;
            }).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(inquirerInfos)) {
            log.error("患者本人信息不存在：patientId={}", patientId);
            return InquirerInitVO.builder().relationList(relationList).build();
        }
        PatientInquirerInfo inquirerInfo = inquirerInfos.get(0);
        Integer selfGender = inquirerInfo.getGender();
        return InquirerInitVO.builder()
            .patientId(inquirerInfo.getPatientId())
            .patientName(inquirerInfo.getName())
            .patientIdCard(inquirerInfo.getIdCard())
            .phone(inquirerInfo.getGuardianPhone())
            .cityId(inquirerInfo.getCityId())
            .address(inquirerInfo.getAddress())
            .contactName(inquirerInfo.getContactName())
            .contactPhone(inquirerInfo.getContactPhone())
            .relationList(relationList)
            .build();
    }

    @Override
    public void insertOrUpdateSelf(Patient patient, PatientBaseParam baseParam) {
        List<PatientInquirerInfo> inquirerInfos = inquirerRepository
            .findByPatientIdAndRelation(patient.getId(), InquirerRelationEnum.ONESELF.getValue());
        PatientInquirerInfo inquirerInfo = null;
        if (CollectionUtils.isNotEmpty(inquirerInfos)) {
            inquirerInfo = inquirerInfos.get(0);
            inquirerInfo.setChangedAt(new Date());
        } else {
            inquirerInfo = new PatientInquirerInfo();
            inquirerInfo.setStatus(PatientInquirerInfo.STATUS_DEFAULT);
            inquirerInfo.setCreatedAt(new Date());
        }
        inquirerInfo.setPatientId(patient.getId());
        inquirerInfo.setRelation(InquirerRelationEnum.ONESELF.getValue());
        inquirerInfo.setName(patient.getName());
        inquirerInfo.setIdCard(patient.getIdCard());
        inquirerInfo.setBirthday(patient.getBirthday());
        inquirerInfo.setGender(patient.getGender());
        inquirerInfo.setGuardianName(patient.getName());
        inquirerInfo.setGuardianIdCard(patient.getIdCard());
        inquirerInfo.setGuardianPhone(patient.getPhone());
        inquirerInfo.setCityId(patient.getCityId());

        // 居住详细地址更新
        if (StringUtils.isNotEmpty(baseParam.getAddress())) {
            inquirerInfo.setAddress(baseParam.getAddress());
        }
        // 紧急联系人信息
        if (StringUtils.isNotEmpty(baseParam.getContactName())) {
            inquirerInfo.setContactName(baseParam.getContactName());
        }
        if (StringUtils.isNotEmpty(baseParam.getContactPhone())) {
            inquirerInfo.setContactPhone(baseParam.getContactPhone());
        }
        // 婚姻状态
        if (null != baseParam.getMaritalStatus()) {
            inquirerInfo.setMaritalStatus(baseParam.getMaritalStatus());
        }

        inquirerInfo.setChildTag(PatientInquirerInfo.CHILD_TAG_NO);

        inquirerRepository.saveOrUpdate(inquirerInfo);
    }

    @Override
    public List<PatientInquirerBO> findByIds(List<Long> ids) throws BusinessException {
        log.info("获取就诊人列表：ids={}", ids);
        Iterable<PatientInquirerInfo> iterable = inquirerRepository.findAllById(ids);
        List<PatientInquirerBO> result = new ArrayList<>();
        iterable.forEach(s -> {
            PatientInquirerBO vo = new PatientInquirerBO();
            BeanUtils.copyProperties(s, vo);
            vo.setRelationName(InquirerRelationEnum.getNameByValue(s.getRelation()));
            vo.setInquirerId(s.getId());
            vo.setAgeYear(s.getAgeYear());
            vo.setAge(StringUtils.isEmpty(vo.getAge()) ? "未知" : vo.getAge());
            if (s.getCityId() != null) {
                City city = apCityRepository.get(s.getCityId());
                vo.setAddress(String.join(",", city.getParentName(), city.getName(), s.getAddress()));
            }
            if (StringUtils.isNotBlank(s.getBirthImage())) {
                vo.setBirthImage(ImgUtil.getWxImgUrl(s.getBirthImage()));
            }
            result.add(vo);
        });
        return result;
    }

    @Override
    public List<InquirerRelationVO> findRelationByPatientId(Long patientId) throws BusinessException {
        Iterable<PatientInquirerInfo> iterable = inquirerRepository.findByPatientIdAndStatus(patientId, PatientInquirerInfo.STATUS_DEFAULT);
        Set<Integer> relations = new HashSet<>();
        iterable.forEach(s -> {
            relations.add(s.getRelation());
        });
        return InquirerRelationEnum.getByValue(relations).entrySet().stream().map(
            s -> InquirerRelationVO.builder()
                .relationId(s.getKey())
                .relationName(s.getValue())
                .build()).collect(Collectors.toList());
    }

    @Override
    public List<PatientInquirerBO> findByPatientAndRelation(Long patientId, Integer relation) throws BusinessException {
        List<PatientInquirerInfo> list = inquirerRepository.findByPatientIdAndRelation(patientId, relation);

        return convertBO(list);
    }

    private PatientInquirerInfo get(Long patientId, Long inquirerId) throws BusinessException {
        PatientInquirerInfo inquirerInfo = inquirerRepository.findByPatientIdAndId(patientId, inquirerId);
        if (inquirerInfo == null) {
            throw new BusinessException(ExceptionCodes.PATIENT_INQUIRER_NOT_EXIST);
        }
        return inquirerInfo;
    }

    @Override
    public List<PatientInquirerBO> findByPatient(Long patientId) throws BusinessException {
        List<PatientInquirerInfo> list = inquirerRepository.findByPatientIdAndStatus(patientId, PatientInquirerInfo.STATUS_DEFAULT);
        return convertBO(list);
    }

    private List<PatientInquirerBO> convertBO(List<PatientInquirerInfo> list) {
        return list.stream().map(s -> {
            PatientInquirerBO bo = new PatientInquirerBO();
            BeanUtils.copyProperties(s, bo);
            if (InquirerRelationEnum.ONESELF.getValue().equals(s.getRelation())) {
                bo.setGuardianIdCard("");
                bo.setGuardianName("");
                bo.setGuardianPhone("");
            }
            String age = s.getAge();
            bo.setAge(StringUtils.isEmpty(age) ? "未知" : age);
            Integer ageYear = s.getAgeYear();
            bo.setAgeYear((null != ageYear && 0 == ageYear) ? null : ageYear);
            bo.setInquirerId(s.getId());
            bo.setRelationName(InquirerRelationEnum.getNameByValue(s.getRelation()));
            if (s.getCityId() != null) {
                City city = apCityRepository.get(s.getCityId());
                bo.setAddress(String.join(",", city.getParentName(), city.getName(), s.getAddress()));
            }
            if (StringUtils.isNotBlank(s.getBirthImage())) {
                bo.setBirthImage(ImgUtil.getWxImgUrl(s.getBirthImage()));
            }
            bo.setChildTag(s.getChildTag());
            return bo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<Long> getInquirerIdsByIdcard(String idcard) {
        List<PatientInquirerInfo> inquirerInfos = inquirerRepository.findByIdCard(idcard);
        return inquirerInfos.stream().map(PatientInquirerInfo::getId).collect(Collectors.toList());
    }

    /**
     * 根据出生日期计算年龄
     *
     * @param birthday
     * @return
     */
    private static int getAgeByBirth(Date birthday) {
        int age = 0;
        try {
            Calendar now = Calendar.getInstance();
            now.setTime(new Date());// 当前时间

            Calendar birth = Calendar.getInstance();
            birth.setTime(birthday);

            if (birth.after(now)) {//如果传入的时间，在当前时间的后面，返回0岁
                age = 0;
            } else {
                age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
                if (now.get(Calendar.DAY_OF_YEAR) < birth.get(Calendar.DAY_OF_YEAR)) {
                    age -= 1;
                }
            }
            return age;
        } catch (Exception e) {//兼容性更强,异常后返回数据
            return 0;
        }
    }

    /**
     * 完善就诊人本人信息
     *
     * @param patientId
     * @param nickName
     * @return
     */
    @Override
    public void supplementMyselfInfo(Long patientId, String nickName) {
        PatientInquirerInfo patientInquirerInfo = inquirerRepository
            .findFirstByPatientIdAndRelation(patientId, InquirerRelationEnum.ONESELF.getValue());
        if (null != patientInquirerInfo && StringUtils.isEmpty(patientInquirerInfo.getName())) {
            patientInquirerInfo.setName(nickName);
            patientInquirerInfo.setChangedAt(new Date());
            inquirerRepository.update(patientInquirerInfo);
        }
    }

    @Override
    public PatientInquirerBO getDefaultInquirerInfoByPatientId(Long doctorId, Long patientId) {
        if (null != doctorId) {
            ConsultSession consultSession = consultSessionRepository.findFirstByPatientIdAndDoctorIdOrderByEndTimeDesc(patientId, doctorId);
            log.info("获取默认就诊人信息 consultSession: {}", JSONUtil.toJsonStr(consultSession));
            if (null != consultSession) {
                Long inquirerId = consultSession.getInquirerId();
                if (null != inquirerId) {
                    PatientInquirerInfo inquirerInfo = inquirerRepository.get(inquirerId);
                    return convertBO(Collections.singletonList(inquirerInfo)).get(0);
                }
            }
        }
        List<PatientInquirerInfo> list = inquirerRepository.findByPatientId(patientId);
        List<PatientInquirerBO> inquirerBOS = convertBO(list);
        List<PatientInquirerBO> patientInquirerBOS = inquirerBOS.stream().filter(i -> i.getRelation() == 0).collect(Collectors.toList());
        PatientInquirerBO patientInquirerBO;
        if (CollectionUtils.isEmpty(patientInquirerBOS)) {
            patientInquirerBO = inquirerBOS.get(0);
            patientInquirerBO.setGuardianIdCard(list.get(0).getGuardianIdCard());
        } else {
            patientInquirerBO = patientInquirerBOS.get(0);
            patientInquirerBO.setGuardianIdCard(list.get(0).getGuardianIdCard());
        }
        return patientInquirerBO;
    }

    @Override
    public PatientInquirerBO getInquirerInfoById(Long inquirerId) {
        PatientInquirerInfo inquirerInfo = inquirerRepository.get(inquirerId);
        return PatientInquirerBO.builder()
            .patientId(inquirerInfo.getPatientId())
            .inquirerId(inquirerId)
            .idCard(inquirerInfo.getIdCard())
            .childTag(inquirerInfo.getChildTag())
            .guardianIdCard(inquirerInfo.getGuardianIdCard())
            .build();
    }

    @Async
    void sendSysMessage(Long doctorId, Long patientId, Long inquirerId) throws BusinessException {
        RedisUtil.valueOps().setEx(CacheConstant.getInquirerInfoPerfectKey(inquirerId), inquirerId.toString(), 5);
        MsgSendParamBO sendParamBO = new MsgSendParamBO();
        sendParamBO.setMsgType(ImConstants.MESSAGE_TYPE_INQUIRER_INFO_PERFECT);
        sendParamBO.setRelation(ImConstants.MESSAGE_RESOURCE_DOCTOR);
        sendParamBO.setDoctorId(doctorId);
        sendParamBO.setPatientId(patientId);
        sendParamBO.setInquirerId(inquirerId);
        sendParamBO.setVisualType(ImConstants.MESSAGE_VISUAL_TYPE_PATIENT);
        sendParamBO.setSysMsgType(ImConstants.SYS_MSG_TYPE_SYSTEM);
        sendParamBO.setLastPlatform(ImConstants.HEADER_ORIGIN_PATIENT_APP);
        sendParamBO.setContent("就诊人信息已完善");
        // 向患者发送系统消息
        imFeginClient.sendSysMessage(sendParamBO);

        // 向医生发送系统消息
        sendParamBO.setRelation(ImConstants.MESSAGE_RESOURCE_PATIENT);
        sendParamBO.setVisualType(ImConstants.MESSAGE_VISUAL_TYPE_DOCTOR);
        imFeginClient.sendSysMessage(sendParamBO);
        RedisUtil.keyOps().delete(CacheConstant.getInquirerInfoPerfectKey(inquirerId));
    }
}
